package com.hjw.exer;

import java.util.Arrays;

/**
 * 学生选课系统，课程类
 * 定义了：课程号、课程名、课程教室、学生信息
 * 课程类应该具备的功能：
 *      添加学生（√）、修改学生信息、查找学生、删除学生信息
 * @author hjwStrart
 * @create 2022-01-07 19:20
 */
public class Course {
    private String id;    //课程编号
    private String courseName;    //课程名
    private String courseroom;    //课程教室
    private Student[] stus;      //选课学生

    public Course() {
    }
    public Course(Student[] stus){
        this.stus = stus;
    }

    public Course(String id, String courseName, String courseroom, Student[] stus) {
        this.id = id;
        this.courseName = courseName;
        this.courseroom = courseroom;
        this.stus = stus;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCourseroom() {
        return courseroom;
    }

    public Student[] getStus() {
        return stus;
    }

    public void setStus(Student[] stus) {
        this.stus = stus;
    }

    public void setCourseroom(String courseroom) {
        this.courseroom = courseroom;
    }


    /**
     * （已测试，无误）添加一个学生到学生集合中，添加成功就将插入位置的索引返回
     * @param stu  添加的学生
     * @return     插入位置的索引
     */
    public Integer addOneStu(Student stu){

        Integer index = getIndex();
        if (index == null){
//           进行扩容操作
            expansion();
        }
        stus[index] = stu;
        return index;
    }

    /**
     * （已测试，无误）对数组进行扩容
     */
    private void expansion(){
        this.stus = Arrays.copyOf(stus,stus.length*2);
        System.out.println(stus.length);
    }

    /**
     * （已测试，无误）获取数组中第一个空元素的索引
     * @return 返回null表明当前数组已满，返回大于等于0的整数代表第一个空元素的索引
     */
    private Integer getIndex(){
        for (int i = 0; i < stus.length; i++) {
            if (stus[i] == null) {
                return i;
            }
        }
        return null;
    }

    /**
     * (已测试，无误)根据名字查询学生，返回学生信息Student
     * @param name  学生姓名
     * @return      学生实例
     */
    public Student selectStudent(String name){
        for (Student student : stus) {
            if (student == null)  break;//查询到空元素直接返回null
            if (student.getName().equals(name)){
                return student;
            }
        }
        return null;
    }

    /**
     * 根据姓名查询学生索引
     * @param name  姓名
     * @return      索引
     */
    public Integer selectStu(String name){
        for (int i = 0; i < stus.length; i++) {
            if (stus[i] == null){
                break;
            }
            if (stus[i].getName().equals(name)){
                return i;
            }
        }
        return null;
    }

    /**
     *(已测试，无误)删除指定位置的元素信息
     * @param index   元素索引
     * @return   删除的元素的索引
     */
    public Integer delectByIndex(Integer index){
        if (index > stus.length || index < 0)
            throw new StringIndexOutOfBoundsException(index);
//        直接将该位置的元素设为null
        stus[index] = null;
//        将数组前移一位
        forwardMoveArrElem(index+1,stus);
        return index;
    }

    /**
     *修改指定姓名的学生信息
     * @param student   学生实例
     * @param name  学生姓名
     */
    public void updateStudentInfo(Student student,String name){

        Integer index = selectStu(name);
        stus[index] = student;
    }

    /**
     * 从指定索引位置开始，继续删除索引为后面指定长度的元素
     * @param index  开始位置
     * @param size   删除的元素个数（index + 1是size的一个元素）
     * @return
     */
    public void delectByIndex(Integer index,Integer size){
        if (index > stus.length || index < 0)
            throw new StringIndexOutOfBoundsException(index);
        stus[index] = null;//删除索引为index的元素
        if (size < 0){
            size = 0;
        }
//        如果size大于等于数组剩下的元素个数，直接将这些元素置为null，不需要移动元素
        if((size + index + 1) - stus.length >= 0){
            for (int i = index + 1; i < stus.length; i++) {
                stus[i] = null;
            }
            return;
        }else{
            forwardMoveArrElem(index+1,stus,size);
        }

//        将数组前移size位
    }

    /**
     * （已测试，无误）将数组从指定索引位开始前移一位
     * @param beginIndex  索引位置
     * @param t   数组
     * @param <T>  类型
     */
    private <T> void forwardMoveArrElem(Integer beginIndex,T[] t){
        if (beginIndex > t.length || beginIndex < 0)
            throw new StringIndexOutOfBoundsException(beginIndex);
        for (int i = beginIndex + 1; i < t.length ; i++) {
            t[i -1] = t[i];
        }
        t[t.length - 1] = null;
    }

    /**
     * (已测试，无误)将数组从指定开始前移指定位数
     * @param beginIndex  开始索引
     * @param t           数组名
     * @param distance    移动距离
     * @param <T>         数组类型
     */
    private <T> void forwardMoveArrElem(Integer beginIndex,T[] t,int distance) {
//        判断起始位置是否合法
        if (beginIndex > t.length || beginIndex < 0)
            throw new StringIndexOutOfBoundsException(beginIndex);
//        判断前移距离是否合法
        if (distance < 0) {//移动距离为零，不移动同时结束方法
            distance = 0;
            return;
        }
        if (t.length - distance <= 0) {  //数组元素最多前移length-1位
            distance = t.length - 1;
        }
        for (int i = 0; i < distance + 1; i++) {//每循环一次前移一位

            forwardMoveArrElem(--beginIndex < 0 ? 0 : beginIndex, stus);
//            for (int j = beginIndex; j < t.length; j++) {
//                t[j -1] = t[j];
//            }

            t[t.length - 1 - i] = null;
        }
    }

    /**
     * （已测试，无误）显示所有学生的基本信息
     */
    public void getAllStuInfo(){
        for (Student student : stus) {
            System.out.println(student);
        }
    }

    /**
     * 显示课程基本信息
     * @return
     */
    @Override
    public String toString() {
        return  "课程号='" + id + '\'' +
                ", 课程名='" + courseName + '\'' +
                ", 课程教室='" + courseroom + '\'';
    }
}
